package com.kuang.threadpool;

import java.util.concurrent.*;

/**
 * 结合业务理解线程池及参数含义：
 *      银行办理业务：
 *      银行大厅 --> 线程池
 *      柜台：5个柜台：2个开设柜台，3个备用柜台  --> 最大核心线程数：5，核心线程数：2,
 *      候客区：3个座位 --> 阻塞队列
 *          1个人进去，直接办理
 *          5个人进去（3个人在候客厅）
 *          8个人进去（5个窗口都开放+3个在候客厅）
 *          9个人进去（多1个人，被拒绝进入，抛出异常）
 *          1个小时后，只剩2个窗口在服务，3个备用柜台就关闭释放
 *
 *  四种拒绝策略：  RejectedExecutionHandler
 *       AbortPolicy()  默认  堕胎策略             第九个进来时，抛出异常
 *       CallerRunsPolicy()  调用者运行策略        第九个进来时，不抛出异常，调用者执行（main主线程执行）
 *       DiscardPolicy()     丢弃策略             第九个进来时，不抛出异常，丢弃任务
 *       DiscardOldestPolicy() 丢弃最老的策略      第九个进来时，不抛出异常，尝试和最早的竞争
 *
 *
 *  最大线程如何定义？
 *      1.CPU密集型，几核，就是几，可以保证CPU效率最高
 *          获取CPU数量：注意：不要写死，代码获取CPU核数，because运维CPU设备比你牛时，你写死了，会被打死！
 *          ①任务管理器查看  ②设备管理器查看  ③代码查看（用这个 Runtime.getRuntime().availableProcessors()）
 *      2.IO密集型，假设有15个大型任务IO十分占用资源，这时设计时，最好设置为 > 2*15 ~ 30核
 *
 */
public class Demo03 {
    public static void main(String[] args) {

        // 1.AbortPolicy()  默认  堕胎策略，抛出异常
        // 创建线程池
        //ThreadPoolExecutor threadPool1 = new ThreadPoolExecutor(
        //        2,
        //        5,
        //        3,
        //        TimeUnit.SECONDS,
        //        new LinkedBlockingQueue<>(3),
        //        Executors.defaultThreadFactory(),
        //        new ThreadPoolExecutor.AbortPolicy()); //拒绝策略1
        //try {
        //    // 使用线程池
        //    for (int i = 1; i <= 100; i++) {
        //        threadPool1.execute(()->{
        //            System.out.println(Thread.currentThread().getName() + ":ok");
        //        });
        //    }
        //}catch (Exception e){
        //    e.printStackTrace();
        //}finally {
        //    // 线程池用完，线程结束，关闭线程池
        //    threadPool1.shutdown();
        //}
        /*
            pool-1-thread-3:ok
            pool-1-thread-5:ok
            pool-1-thread-4:ok
            pool-1-thread-1:ok
            pool-1-thread-2:ok
            pool-1-thread-4:ok
            pool-1-thread-5:ok
            pool-1-thread-3:ok
            第九个进来时，抛出RejectedExecutionException
         */



        // 2.CallerRunsPolicy()  调用者运行策略，不抛出异常
        // 创建线程池
        //ThreadPoolExecutor threadPool2 = new ThreadPoolExecutor(
        //        2,
        //        5,
        //        3,
        //        TimeUnit.SECONDS,
        //        new LinkedBlockingQueue<>(3),
        //        Executors.defaultThreadFactory(),
        //        new ThreadPoolExecutor.CallerRunsPolicy()); //拒绝策略2
        //try {
        //    // 使用线程池
        //    for (int i = 1; i <= 9; i++) {
        //        threadPool2.execute(()->{
        //            System.out.println(Thread.currentThread().getName() + ":ok");
        //        });
        //    }
        //}catch (Exception e){
        //    e.printStackTrace();
        //}finally {
        //    // 线程池用完，线程结束，关闭线程池
        //    threadPool2.shutdown();
        //}
        /*
            pool-1-thread-4:ok
            pool-1-thread-3:ok
            pool-1-thread-1:ok
            main:ok              第9个人，主线程来处理，谁让他进入线程池的，就回到原来地方处理，就像公司让你去银行办理，银行拒绝，让你去公司办理，公司可以代办
            pool-1-thread-4:ok
            pool-1-thread-4:ok
            pool-1-thread-2:ok
            pool-1-thread-1:ok
            pool-1-thread-5:ok
         */



        // 3.DiscardPolicy()  丢弃策略，不抛出异常
        // 创建线程池
        //ThreadPoolExecutor threadPool3 = new ThreadPoolExecutor(
        //        2,
        //        5,
        //        3,
        //        TimeUnit.SECONDS,
        //        new LinkedBlockingQueue<>(3),
        //        Executors.defaultThreadFactory(),
        //        new ThreadPoolExecutor.DiscardPolicy()); //拒绝策略3
        //try {
        //    // 使用线程池
        //    for (int i = 1; i <= 9; i++) {
        //        threadPool3.execute(()->{
        //            System.out.println(Thread.currentThread().getName() + ":ok");
        //        });
        //    }
        //}catch (Exception e){
        //    e.printStackTrace();
        //}finally {
        //    // 线程池用完，线程结束，关闭线程池
        //    threadPool3.shutdown();
        //}
        /*
            pool-1-thread-1:ok
            pool-1-thread-5:ok
            pool-1-thread-1:ok
            pool-1-thread-1:ok
            pool-1-thread-4:ok
            pool-1-thread-3:ok
            pool-1-thread-2:ok
            pool-1-thread-5:ok  不要第9个人
         */


        // 4.DiscardOldestPolicy()  抛弃保单策略，不抛出异常
        // 创建线程池
        ThreadPoolExecutor threadPool4 = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy()); //拒绝策略4
        try {
            // 使用线程池
            for (int i = 1; i <= 9; i++) {
                threadPool4.execute(()->{
                    System.out.println(Thread.currentThread().getName() + ":ok");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 线程池用完，线程结束，关闭线程池
            threadPool4.shutdown();
        }
        /*
            pool-1-thread-1:ok
            pool-1-thread-4:ok
            pool-1-thread-1:ok
            pool-1-thread-3:ok
            pool-1-thread-2:ok
            pool-1-thread-1:ok
            pool-1-thread-4:ok
            pool-1-thread-5:ok  第9个进来，尝试和最早 的竞争，不抛出异常，这里没有竞争到，就抛弃了
         */

        /*
            获取CPU核数
         */
        ThreadPoolExecutor threadPool5 = new ThreadPoolExecutor(
                2,
                Runtime.getRuntime().availableProcessors(),   //线程池大小设置:获取当前运行设备CPU核数
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy()); //拒绝策略4
    }
}
